package rep

import (
    "../pb"
    "../common"
    "sync"
)

type SecondContext struct {
    isCheckpointRunning       bool
    mu                        sync.RWMutex
    checkpointTask            *common.Task
    checkpointCompletedTask   *common.Task
    catchupWithPrivateLogTask *common.Task
}

func (sc *SecondContext) checkpointIsRunning() bool {
    sc.mu.RLock()
    defer sc.mu.RUnlock()
    return sc.isCheckpointRunning
}

type PrimaryContext struct {
    membership                    *pb.PartitionConfiguration
    learners                      map[common.Node]RemoteLearnerState //learner state
    nodeStatuses                  map[common.Node]pb.PartitionStatus
    mu                            sync.RWMutex
    lastPrepareTimeMs             uint64
    lastPrepareOffsetOnNewPrimary int64
    nextLearningVersion           uint64
    groupCheckTask                *common.Task
    groupCheckPendingReplies      map[common.Node]*common.Task
    reconfigurationTask           *common.Task
    checkpointTask                *common.Task
}


func (pc *PrimaryContext) getReplicaConfig(stat pb.PartitionStatus, learnerSignature uint64) *pb.ReplicaConfiguration {
    pc.mu.RLock()
    defer pc.mu.RUnlock()
    return &pb.ReplicaConfiguration{
        Pid:              pc.membership.Pid,
        Primary:          pc.membership.Primary,
        Ballot:           pc.membership.Ballot,
        Status:           stat,
        LearnerSignature: learnerSignature,
    }
}

func (pc *PrimaryContext) addLearner(node common.Node) uint64 {
    pc.mu.Lock()
    defer pc.mu.Unlock()
    stat, ok := pc.learners[node]
    if !ok {
        pc.nextLearningVersion++
        rs := RemoteLearnerState{
            prepareStartOffset: -1,
            signature:          pc.nextLearningVersion,
        }
        pc.learners[node] = rs
        pc.nodeStatuses[node] = pb.PartitionStatus_PS_PotentialSecondary
        return rs.signature
    }
    return stat.signature
}

func (pc *PrimaryContext) isReconfigurationTaskRunning() bool {
    pc.mu.RLock()
    defer pc.mu.RUnlock()
    return pc.reconfigurationTask != nil
}

type PotentialSecondaryContext struct {
    learningVersion               uint64
    learningStartTimeNs           uint64
    learningCopyFileCount         uint64
    learningCopyFileSize          uint64
    learningCopyBufferSize        uint64
    learningStatus                pb.LearnerStatus
    learningRoundIsRunning        bool
    learningStartPrepareOffset    int64
    mu                            sync.RWMutex
    delayLearningTask             *common.Task
    learningTask                  *common.Task
    learnRemoteFilesTask          *common.Task
    learnRemoteFilesCompletedTask *common.Task
    catchupWithPrivateLogTask     *common.Task
    completionNotifyTask          *common.Task
}

type RemoteLearnerState struct {
    signature          uint64
    prepareStartOffset int64
    offset             int64
    timeoutTask        *common.Task
    lastLearnLogFile   string
}
